/** \file ezlcd3xx.h
 * Header for the ezlcd3xx Arduino library for ezLCD-3xx devices by EarthLCD.com
 * The library communicates with the ezLCD via a hardware and/or serial port
 */
 
/*
 * Written and maintained by Sergey Butylkov. 
 * Created on behalf of EarthLCD.com a dba of Earth Computer Technologies Inc.
 *
 * Project home: http://arduino-ezlcd3xx.googlecode.com
 *
 * Copyright (C) 2012 Sergey Butylkov
 * Copyright (C) 2012 EarthLCD.com a dba of Earth Computer Technologies, Inc.
 * 
 * This work is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version. This work is distributed in the hope that it will be 
 * useful, but without any warranty; without even the implied warranty of 
 * merchantability or fitness for a particular purpose. See the GNU Lesser 
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef _EZLCD3XX_H
#define _EZLCD3XX_H

#include <SoftwareSerial.h>
#include <stddef.h> /* For size_t */
#include <stdint.h> /* for uint8_t */
class Stream;       /* Forward declaration of Stream to be used
                     * in the EzLCD3xx abstract class */
                   
/* The following are preprocessor directives. The affect how the
 * the library code is being compiled. */

/**
 * Set to \c 1 to send brief numeric commands that use less bandwidth and result
 * in slightly smaller code.
 * Set to \c 0 to enable sending full length alphabetic commands. Useful for
 * debugging.
 */
 #define EZLCD_MINIMALTX 1

/**
 * Set to \c 1 to force ezLCD into non-verbose non-echo mode after communication
 * with it has been establishes. This ensures the the fastest communication
 * with the ezLCD.
 * Set to \c 0 to allow ezLCD to continue operating in a verbose and/or echo mode
 * after it has been found. Useful for debugging.
 */
#define EZLCD_MINIMALRX 1

/**
 * Set to \c 1 to enable debugging the library over the hardware serial port.
 * When doing so, make sure you are using \c EzLCD3xx_SW class and not using
 * the hardware serial in any other way.
 * Set to \c 0 to disable serial debugging, which frees up the hardware serial
 * port and additional processing, and results in smaller code. Keep this at
 * \c 0 when you are using EzLCD3xx_HW class.
 */
#define EZLCD_SERIALDEBUG 0

/**
 * Buffer size used internally by the \c ezLCD3xx class. If you are printing
 * VERY long strings to the ezLCD you will need to increase this
 */
#define EZLCD_BUFSIZE 64

/**
 * Set to \c 1 to globally declare numeric constants used by the \c EzLCD3xx
 * class. 
 * Set to \c 0 to declare the numeric constants as enums local to the \c EzLCD3xx
 * class
 */
#define EZLCD_GLOBALENUMS 1

/* The following are constants used by the EzLCD3xx library. These can be
 * declared in a global scope (easier to use for novice developers, but can
 * cause problems in larger programs), or they can be limited to the scope of
 * the class (will require \c EzLCD3xx::CONSTANT syntax). See \c
 * EZLCD_GLOBALENUMS above. */

/** Enum values for orientation */
#define EZLCD_ENUM_ORIENTATION \
enum { HORIZONTAL=0, VERTICAL=1 };

/** Enum values for alignment */
#define EZLCD_ENUM_ALIGNMENT \
enum { CENTER=0x100, TOP=0x200, RIGHT=0x400, BOTTOM=0x800, LEFT=0x1000 };

/** Enum values for convenient combined alignment */
#define EZLCD_ENUM_COMBALIGN \
enum { LEFTTOP = TOP | LEFT, RIGHTTOP = TOP | RIGHT };             \
enum { TOPLEFT = LEFTTOP, TOPRIGHT = RIGHTTOP };                   \
enum { LEFTBOTTOM = BOTTOM | LEFT, RIGHTBOTTOM = BOTTOM | RIGHT }; \
enum { BOTTOMLEFT = LEFTBOTTOM, BOTTOMRIGHT = RIGHTBOTTOM };

/** Enum for widget and picture options */
#define EZLCD_ENUM_WIDGETS \
enum { DRAW=0x1, DISABLED=0x4, PRESSED=0x2000, TOGGLE=0x8 };       \
enum { REMOVE=0x10, REDRAW=0x20, HDISABLED=0x40, VDISABLED=0x80 }; \
enum { CHECKED=0x2000, SELECTED=0x2000, FIRST=0x4000 };            \
enum { FIRSTANDSELECTED = FIRST | SELECTED };                      \
enum { RING=0x2000, ACCURACY=0x4000 };                             \
enum { CLOCKWISE=0x2000, COUNTERCLOCKWISE=0x4000 };                \
enum { NONE=0, DOWNSIZE=0x1, BOTH = DOWNSIZE | CENTER };           \

/** Enum for choice */
#define EZLCD_ENUM_CHOICE \
enum { YES=1, NO=0, CANCEL=-1 };

/* Declares enums in the global scope when \c EZLCD_GLOBALENUMS is \c 1 */
#if EZLCD_GLOBALENUMS
EZLCD_ENUM_ORIENTATION
EZLCD_ENUM_ALIGNMENT
EZLCD_ENUM_COMBALIGN
EZLCD_ENUM_WIDGETS
EZLCD_ENUM_CHOICE
#endif

/**
 * Communicates with the Arduino via software and/or hardware serial port. This
 * is a virtual class so the user cannot instantiate it. Instead the user will
 * instantiate an \c EzLCD3xx_HW or \c EZLCD3xx_SW classes. See the end of this
 * header file.
 */
class EzLCD3xx
{   
public:  
    /** Class constructor */
    EzLCD3xx();

    /** Class destructor */
    ~EzLCD3xx();

    /**
     * Initialize communication at the specified baud rate and wait for ezLCD
     * to get ready to accept commands. Implementation depends on hardware vs
     * software serial.
     * \param[in]  baud    Baud rate
     */
    virtual void begin( long baud )=0;
    /* TODO: Specify number of times ping is attempted */

    /**
     * Reset ezLCD and re-establish communication.
     */
    void reset();

    /**
     * Clear screen to a specific color id and clear widgets.
     * \param[in] id    Numeric value for the color. 0 (black) by default.
     */
    void cls( int id=0 );

    /**
     * Clear screen to a specific color and clear widgets.
     * \param[in] color    Null-terminated string describing color.
     */
    void cls( const char *color );

    /**
     * Asks LCD to send acknowledge with PONG.
     * \retval true     Ping successful.
     * \retval false    Ping failed.
     */
    bool ping();

    /**
     * Returns whether the class was configured for verbose
     * \retval true    The class is configured for verbose.
     * \retval false   The class is configured for NON-verbose.
     */    
    bool verbose() { return m_verbose; }

    /**
     * Enable or disable verbose
     * \param[in]  val  \c true to enable verbose. \c false to disable verbose
     */
    void verbose( bool val );

    /**
     * Returns whether the class was configured for echo
     * \retval  true     The class is configured for echo.
     * \retval  false    The class is configured for NO echo
     */
    bool echo() { return m_echo; }

    /**
     * Enable or disable echo
     * \param[in]  val    \c true to enable echo. \c false to disable echo.
     */
    void echo( bool val );

    /**
    * Return current brightness setting.
    * \return    Brightness in 0-100.
    */
    int light();

    /**
     * Set brightness.
     * \param[in]  brightness    Brightness in 0-100.
     */
     void light( int brightness );

    /**
     * Sets the current color by color ID.
     * \param[in]  id    Numeric color ID.
     */
    void color( int id );

    /**
     * Return current color.
     * \param[out]  red    Red value in 0-255.
     * \param[out]  green  Green value in 0-255.
     * \param[out]  Blue   Blue value in 0-255.
     */
    void color( uint8_t *red, uint8_t *green, uint8_t *blue );
    
    /**
     * Sets a color index to a specific RGB value
     * \param[in]  id    Numeric color ID.
     * \param[in]  red   Red value in 0-255.
     * \param[in]  green Green value in 0-255.
     * \param[in]  blue  Blue value in 0-255.
     */
    void colorid( int id, uint8_t red, uint8_t green, uint8_t blue );

    /**
     * Get RGB value of a color index
     * \param[in]  id    Numeric color ID.
     * \param[out] red   Red value in 0-255.
     * \param[out] green Green value in 0-255.
     * \param[out] blue  Blue value in 0-255.
     */
    void colorid( int id, uint8_t *red, uint8_t *green, uint8_t *blue );

    /**
     * Set current font to an internal factory font.
     * \param[in]  id    Factory font index. Currently 0 to 5. Default is 0,
     *                   default medium font.
     */ 
    void font( int id=0 );

    /**
     * Set current font to a programmable font (ezf file) from flash drive
     * \param[in]  fontname    Font filename on the ezLCD filesystem.
     */
    void font( const char* fontname );

    /**
     * Set font index (used by themes) to a programmable font (ezf file) 
     * from flash drive.
     * \param[in]  id        Font ID.
     * \param[in]  fontname  Font filename on the ezLCD filesystem.
     */
    void fontw( int id, const char* fontname );

    /**
     * Set current font orientation to horizontal or vertical
     * \param[in]  orientation    \c HORIZONTAL for horizontal orientation.
     *                            \c VERTICAL for vertical orientation.
     */
    void fonto( int orientation );

    /**
     * Returns current font orientation.
     * \retval  HORIZONTAL    Horizontal orientation.
     * \retval  VERTICAL      Vertical orientation.
     */
    int fonto();

    /**
     * Invoke a touch screen calibrate.
     */
    void calibrate();

    /** Set current line width
     * \param[in]  width    Line width in pixels. Can be 1 or 3 pixels.
     */
    void linewidth( int width );

    /**
     * Returns current line width
     * \return    Line width in pixels. 1 or 3 pixels.
     */
    int linewidth();

    /**
     * Set line type to solid, dot or dash.
     * \param[in]  type    \c 0 is solid, increasing number increases spacing
     *                     between dots.
     */
    void linetype( int type );

    /**
     * Return current line type.
     * \return    \c 0 when solid, higher number for dash and even higher for
     *            dot.
     */
    int linetype();

    /**
     * Return the maximum allowed x-coordinate.
     * \return    Maximum allowed x-coordinate in pixels.
     */
    uint16_t xmax();

    /**
     * Return the screen width.
     * \return    Screen width in pixels.
     */
    inline uint16_t width();

    /**
     * Return the maximum allowed y-coordinate.
     * \return    Maximum allowed y-coordinate in pixels.
     */
    uint16_t ymax();

    /**
     * Return the screen height.
     * \return    Screen height in pixels.
     */
    inline uint16_t height();

    /**
     * Set the drawing cursor to location x,y on screen.
     * \param[in]  x    x-coordinate in pixels.
     * \param[in]  y    y-coordinate in pixels.
     */
    void xy( uint16_t x, uint16_t y );

    /**
     * Set the drawing cursor to a preset aligned location.
     * \param[in]  align    Alignment. Allowed values are \c LEFTTOP, 
     *                      \c TOPLEFT, \c TOP, \c RIGHTTOP, \c TOPRIGHT,
     *                      \c LEFT, \c CENTER, \c RIGHT, \c LEFTBOTTOM,
     *                      \c BOTTOMLEFT, \c BOTTOM, \c RIGHTBOTTOM, 
     *                      \c BOTTOMRIGHT
     */
    void xy( uint32_t align );

    /**
     * Return current x,y drawing location.
     * \param[out]  x    x-coordinate in pixels.
     * \param[out]  y    y-coordinate in pixels.
     */
    void xy( uint16_t *x, uint16_t *y );

    /**
     * Store current x and y into x,y array on ezLCD.
     * \param[in]  id    Index where x and y is stored.
     */
    void xy_store( int id );

    /**
     * Restore current x and y from the x,y array on ezLCD.
     * \param[in]  id    Index from which x and y are restored.
     */
    void xy_restore( int id );

    /**
     * Store string at an index in the string array on ezLCD.
     * \param[in]  id    String ID at which to store.
     * \param[in]  str   Null-terminated string to store.
     */
    void string( int id, const char *str );

    /**
     * Get string from the string array using id.
     * \param[in]  id    String index to get.
     * \return           String obtained from the ezLCD. If you want to use this
     *                   string later you must make a copy of the string at this
     *                   pointer before issuing another communication command by
     *                   this class.
     */
    const char* string( int id );

    /**
     * Draw a pixel at the current x and y with the current color.
     */
    void plot();

    /**
     * Draw a pixel at a specified x,y with current color.
     * \param[in]  x    x-coordinate in pixels.
     * \param[in]  y    y-coordinate in pixels.
     */
    void plot( uint16_t x, uint16_t y );

    /**
     * Draw a line from the current x,y to the specified x,y
     * \param[in]   x    x-coordinate in pixels to draw the line to.
     * \param[in]   y    y-coordinate in pixels to draw the line to.
     */
    void line( uint16_t x, uint16_t y );

    /**
     * Draw a box from the current x,y with specified width, height, and fill.
     * \param[in]   width    Box width in pixels.
     * \param[in]   height   Box height in pixels.
     * \param[in]   fill     Set to \c true to fill the solid with box. Default
     *                       is \c false which only draws the box outline.
     */
    void box( uint16_t width, uint16_t height, bool fill=false );

    /**
     * Draw a circle at current x,y with the specified radius and fill.
     * \param[in]  radius    Circle radius in pixels.
     * \param[in]  fill      Set to \c true to fill the circle solid with color.
     *                       Default is \c false which only draws the circle
     *                       outline
     */
    void circle( uint16_t radius, bool fill=false );

    /**
     * Draw an arc with the specified radius, start angle and end angle.
     * \param[in]  radius    Arc radius in pixels.
     * \param[in]  start     Start angle in degrees.
     * \param[in]  end       End angle in degrees.
     */
    void arc( uint16_t radius, int16_t start, int16_t end );

    /**
     * Draw a pie with the specified radius, start angle and end angle.
     * \param[in]  radius    Arc radius in pixels.
     * \param[in]  start     Start angle in degrees.
     * \param[in]  end       End angle in degrees.
     */
    void pie( uint16_t radius, int16_t start, int16_t end );

    /**
     * Draw a picture by id on ezLCD. Same as \c image() function.
     * \param[in]  id       ID of the picture to display.
     * \param[in]  x        x-coordinate in pixels of where to draw.
     * \param[in]  y        y-coordinate in pixels of where to draw.
     * \param[in]  options  Allowed values are \c CENTER to draw the picture
     *                      centered, \c DOWNSIZE to downsize the picture,
     *                      \c BOTH to do both and \c NONE to do neither.
     */
    void picture( int id, uint16_t x, uint16_t y, uint32_t options=NONE );

    /**
     * Draw a picture from file on the ezLCD. Same as \c image() function.
     * \param[in]  filename  Filename of the picture to display. Must include
     *                       extension.
     * \param[in]  x         x-coordinate in pixels of where to draw.
     * \param[in]  y         y-coordinate in pixels of where to draw.
     * \param[in]  options   Allowed values are \c CENTER to draw the picture
     *                       centered, \c DOWNSIZE to downsize the picture,
     *                       \c BOTH to do both and \c NONE to do neither.
     */
    void picture( const char *filename, uint16_t x, uint16_t y,
                  uint32_t options=NONE );

    /**
     * Draw an image by id on ezLCD. Same as \c picture() function.
     * \param[in]  id       ID of the image to display.
     * \param[in]  x        x-coordinate in pixels of where to draw.
     * \param[in]  y        y-coordinate in pixels of where to draw.
     * \param[in]  options  Allowed values are \c CENTER to draw the picture
     *                      centered, \c DOWNSIZE to downsize the picture,
     *                      \c BOTH to do both and \c NONE to do neither.
     */
    inline void image( int id, uint16_t x, uint16_t y, uint32_t options=NONE );

    /**
     * Draw an image from file on the ezLCD. Same as \c picture() function.
     * \param[in]  filename  Filename of the image to display. Must include
     *                       extension.
     * \param[in]  x         x-coordinate in pixels of where to draw.
     * \param[in]  y         y-coordinate in pixels of where to draw.
     * \param[in]  options   Allowed values are \c CENTER to draw the picture
     *                       centered, \c DOWNSIZE to downsize the picture,
     *                       \c BOTH to do both and \c NONE to do neither.
     */
    inline void image( const char *filename, uint16_t x, uint16_t y,
                uint32_t options=NONE );

    /**
     * Enable or disable the clip area.
     * \param[in]  enable    \c true to enable, \c false to disable.
     */
    void clipenable( bool enable );

    /**
     * Set the clip area to protect the surrounding area from change. The
     * parameters are limiting coordinates of the clip area.
     * \param[in]  left    Left edge of the clip area in pixels.
     * \param[in]  top     Top edge of the clip area in pixels.
     * \param[in]  right   Right edge of the clip area in pixels.
     * \param[in]  bottom  Bottom edge of the clip area in pixels.
     */
    void cliparea( uint16_t left, uint16_t top, 
                   uint16_t right, uint16_t bottom );

    /**
     * Print a string from the string array on ezLCD by id.
     * \param[in]  id      String ID.
     * \param[in]  align   Text alignment. Allowed values are \c LEFTTOP, 
     *                     \c TOPLEFT, \c TOP, \c RIGHTTOP, \c TOPRIGHT,
     *                     \c LEFT, \c CENTER, \c RIGHT, \c LEFTBOTTOM,
     *                     \c BOTTOMLEFT, \c BOTTOM, \c RIGHTBOTTOM, 
     *                     \c BOTTOMRIGHT, or \c NONE.
     */
    void print( int id, uint32_t alignment=0 );

    /**
     * Print string to the display at the current x,y.
     * \param[in]  str     Null-terminated string to print.
     * \param[in]  align   Text alignment. Allowed values are \c LEFTTOP, 
     *                     \c TOPLEFT, \c TOP, \c RIGHTTOP, \c TOPRIGHT,
     *                     \c LEFT, \c CENTER, \c RIGHT, \c LEFTBOTTOM,
     *                     \c BOTTOMLEFT, \c BOTTOM, \c RIGHTBOTTOM, 
     *                     \c BOTTOMRIGHT, or \c NONE.
     */
    void print( const char *str, uint32_t alignment=0 );

    /**
     * Wait for touch and release of the touch screen.
     * \param[in]  timeout    Timeout value in milliseconds before we give up
     *                        on waiting. Default is very long.
     */
    void wait( unsigned long timeout=(unsigned long)-1 );

    /**
     * Wait for touch.
     * \param[in]  timeout    Timeout value in milliseconds before we give up
     *                        on waiting. Default is very long.
     */
    void waitt( unsigned long timeout=(unsigned long)-1 );

    /**
     * Wait for release of touch.
     * \param[in]  timeout    Timeout value in milliseconds before we give up
     *                        on waiting. Default is very long.
     */
    void waitnt( unsigned long timeout=(unsigned long)-1 );

    /**
     * Record a macro to the internal flash drive.
     * \param[in]  name    Filename for the macro. Specifying the extension is 
     *                     NOT necessary.
     */
    void record( const char *name );

    /**
     * Play a macro.
     * \param[in]  name    Filename for the macro. Specifying the extension is 
     *                     NOT necessary.
     */
    void play( const char *name );

    /**
     * Stop playing a macro
     */
    void stop();

    /**
     * Pause macro exection for the specified amount of time.
     * \param[in]  msec    Delay in milliseconds.
     */
    void pause( int msec );

    /**
     * Enable or disable looping of a macro.
     * \param[in]  val    \c true to enable looping. \c false to disable
     *                    looping.
     */
    void loop( bool val );

    /**
     * Set delay between processing each line of a macro.
     * \param[in]  msec    Delay in milliseconds.
     */
    void speed( int msec );

    /**
     * Configure a general purpose IO pin (1-9) on the ezLCD for input or
     * output.
     * \param[in]  port    Port number on the ezLCD.
     * \param[in]  type    \c INPUT for input and \c OUTPUT for outut.
     */
    void cfgio( uint8_t port, uint8_t type );

    /**
     * Write data to a general purpose IO pin (1-9). The pin must be configured
     * for output.
     * \param[in]  port    Port number on the ezLCD.
     * \param[in]  data    \c 0 to set the pin to low. \c 1 to set the pin high.
     */
    void io( uint8_t port, int data );

    /**
     * Read data from a general purpose IO pin (1-9). The pin must be configured
     * for input
     * \param[in]  port    Port number on the ezLCD.
     * \retval     0       Pin is low.
     * \retval     1       Pin is high.
     * \retval     -1      Failure.
     */
    int io( uint8_t port );

    /**
     * Show a YES, NO and CANCEL prompt, wait for input and return the result.
     * \param[in]  str     String to display in the prompt
     * \param[in]  theme   Theme to use for drawing the prompt.
     * \param[in]  timeout Timeout value in milliseconds before giving up on
     *                     waiting. Default is very long.
     * \retval     YES     User pressed Yes.
     * \retval     NO      User pressed No.
     * \retval     CANCEL  User pressed Cancel.
     */
    int choice( const char *str, int theme,
                unsigned long timeout = (unsigned long)-1 );

    /**
     * Set up a widget theme
     * \param[in] index             Theme Index
     * \param[in] embossDkColor     Dark Emboss color used for 3-D effect of
     *                              objects.
     * \param[in] embossLtColor     Light Emboss color used for 3-D effect of
     *                              objects .
     * \param[in] textColor0        For text, Useage may vary from one widget
     *                              to another, wether the widget is in focus or
     *                              not.
     * \param[in] textColor1        For text when pressed. Useage may vary from
     *                              one widget to another.
     * \param[in] textColorDisabled Color of objects that are disabled.
     * \param[in] color0            For objects. Usage may vary from one object
     *                              to another, wether the widget is in focus or
     *                              not.
     * \param[in] color1            For objects when pressed. Useage may vary 
     *                              from one object to another.
     * \param[in] colorDisabled     Used to render objects that are disabled.
     * \param[in] commonBkColor     Used to hide objects from screen but still
     *                              active.
     * \param[in] fontw             Font id associated with this theme.
     */
    void theme( int index, int embossDkColor, int embossLtColor,
                int textColor0, int textColor1, int textColorDisabled,
                int color0, int color1, int colorDisabled,
                int commonBkColor, int fontw );

    /**
     * Draw/alter a button widget.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  radius    Controls roundness of the button edges.
     *                       Radius of \c 0 (default) means button corners are
     *                       perfect right angles. Radius of half the size of
     *                       the button results in an edge that is round.
     * \param[in]  align     Text alignment. Allowed values are \c CENTER
     *                       (default), \c LEFT, \c RIGHT or \c BOTTOM
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW to just draw a button,
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled button,
     *                       \c PRESSED to draw a pressed button,
     *                       \c TOGGLE to toggle the pressed state of an
     *                       existring button.
     */
    void button( int id, int theme, int strid,
                 uint16_t x, uint16_t y, uint16_t width, uint16_t height, 
                 uint16_t radius=0, uint32_t align=CENTER, uint32_t option=DRAW );

    /**
     * Draw/alter a checkbox.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW to just draw a checkbox (default),
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled checkbox,
     *                       \c CHECKED to draw a checked checkbox,
     *                       \c REDRAW to redraw a checkbox.
     */
     
     
    void checkbox( int id, int theme, int strid,
                   uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                   uint32_t option=DRAW );
                   
    /** Draw/alter a radio button widget.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW to draw a radio button (default),
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled radio button,
     *                       \c SELECTED to draw a selected radio button,
     *                       \c FIRST to draw a radio button that is first in
     *                       a group,
     *                       \c FIRSTANDSELECTED to draw a radio button that is
     *                       first in a group and is also selected.
     */
    void radio( int id, int theme, int strid,
                uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                uint32_t option=DRAW );

    /**
     * Create/alter a groupox.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW or \c LEFT to just draw a left-aligned
     *                       groupbox (default),
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled left-aligned
     *                       groupbox,
     *                       \c RIGHT to draw a right-aligned groupbox,
     *                       \c CENTER to draw a center-aligned groupbox.
     */
    void gbox( int id, int theme, int strid, 
               uint16_t x, uint16_t y, uint16_t width, uint16_t height,
               uint32_t option=LEFT );
                   
    /**
     * Creates/alter a progress widget.
     * \param[in]  id          Widget ID to assign.
     * \param[in]  theme       Theme ID to use.
     * \param[in]  x           Starting x-coordinate in pixels.
     * \param[in]  y           Starting y-coordinate in pixels.
     * \param[in]  width       Width in pixels.
     * \param[in]  height      Height in pixels.
     * \param[in]  initial     Initial numeric reading of the progress bar.
     *                         Default is \c 0.
     * \param[in]  range       Maximum allowed value of the progress bar.
     *                         Default is \c 100.
     * \param[in]  orientation \c HORIZONTAL (default) or \c VERTICAL.
     * \param[in]  option      Option. Allowed values are:
     *                         \c DRAW to draw a horizontal progress (default),
     *                         \c DISABLED to draw a disabled progress widget,
     *                         \c REMOVE (currently unsupported),
     *                         \c REDRAW (deprecated) - use \c progress_value()
     *                         function.
     */
    void progress( int id, int theme,
                   uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                   int initial=0, int range=100, 
                   int orientation=HORIZONTAL, uint32_t option=DRAW );

    /**
     * Create/alter a static text widget.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW to draw a left-aligned static text
     *                       (default),
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled static widget,
     *                       \c RIGHT to draw a right-aligned static widget,
     *                       \c CENTER to draw a center-aligned static widget,
     *                       \c REDRAW to redraw a static test widget.
     */
    void statictext( int id, int theme, int strid,
                     uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                     uint32_t option=LEFT );

    /**
     * Creates/alter a digital meter widget.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  initial   Initial numeric value of the meter. Default is \c
     *                       0.
     * \param[in]  digits    Total number of digits. Default is \c 2.
     * \param[in]  dotpos    Dot position counting digits from the left. Default
     *                       is 1.
     * \param[in]  framed    \c true add a frame to the widget. \c false for
     *                       no frame (default).
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW or to draw a left-aligned digital meter
     *                       (default),
     *                       \c REMOVE (currently unsupported),
     *                       \c DISABLED to draw a disabled left-aligned digital
     *                       meter,
     *                       \c RIGHT to draw a right-aligned digital meter,
     *                       \c CENTER to draw a center-aligned digital meter,
     *                       \c REDRAW (deprecated). Use dmeter_value()
     *                       function.
     */
    void dmeter( int id, int theme,
                 uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                 int initial=0, int digits=2, int dotpos=1, 
                 bool framed=false, uint32_t option=LEFT );

    /**
     * Creates/alter an analog meter widget.
     * \param[in]  id        Widget ID to assign.
     * \param[in]  theme     Theme ID to use.
     * \param[in]  strid     String ID to use for text.
     * \param[in]  x         Starting x-coordinate in pixels.
     * \param[in]  y         Starting y-coordinate in pixels.
     * \param[in]  width     Width in pixels.
     * \param[in]  height    Height in pixels.
     * \param[in]  initial   Initial numeric value of the meter. Default is \c
     *                       0.
     * \param[in]  min       Minimum reading of the meter. Default is \c 0.
     * \param[in]  max       Maximum reading of the meter. Default is \c 100.
     * \param[in]  option    Option. Allowed values are:
     *                       \c DRAW to just draw an analog meter (default).
     *                       \c REMOVE (currently unsupported),
     *                       \c RING to draw a ring meter widget,
     *                       \c ACCURACY to draw an accuracy meter widget,
     *                       \c REDRAW (deprecated) - use \c ameter_value()
     *                       function.
     */
    void ameter( int id, int theme, int strid,
                 uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                 int initial=0, int min=0, int max=100, uint32_t option=DRAW );

    /**
     * Create/alter a dial widget.
     * \param[in]  id         Widget ID to assign.
     * \param[in]  theme      Theme ID to use.
     * \param[in]  strid      String ID to use for text.
     * \param[in]  x          Starting x-coordinate in pixels.
     * \param[in]  y          Starting y-coordinate in pixels.
     * \param[in]  radius     Radius of the dial in pixels.
     * \param[in]  resolution Resolution of the dial in degrees. Default is \c
     *                        10.
     * \param[in]  initial    Initial numeric position of the dial. Default is
     *                        \c 0.
     * \param[in]  max        Maximum numeric position of the dial. Default is
     *                        \c 100.
     * \param[in]  option     Option. Allowed values are:
     *                        \c DRAW to just draw a dial (default),
     *                        \c REMOVE (currently unsupported),
     *                        \c DISABLED to draw a disabled dial,
     *                        \c CLOCKWISE draw a dial that turns clockwise,
     *                        \c COUNTERCLOCKWISE to draw a dial that turns
     *                        counterclockwise.
     */
    void dial( int id, int theme, int strid,
               uint16_t x, uint16_t y, uint16_t radius,
               int resolution=10, int initial=0, int max=100,
               uint32_t option=DRAW );

    /**
     * Ceate/alter a slider widget.
     * \param[in]  id          Widget ID to assign.
     * \param[in]  theme       Theme ID to use.
     * \param[in]  strid       String ID to use for text.
     * \param[in]  x           Starting x-coordinate in pixels.
     * \param[in]  y           Starting y-coordinate in pixels.
     * \param[in]  width       Width in pixels.
     * \param[in]  height      Height in pixels.
     * \param[in]  orientation \c HORIZONTAL (default) or \c VERTICAL.
     * \param[in]  scrollbar   \c true to create/alter a scrollbar widget. \c
     *                         false to create a regular slider widget
     *                         (default).
     * \param[in]  initial     Initial numeric value of the slider. Default is
     *                         \c 0.
     * \param[in]  max         Maximum numeric value of the slider. Default is
     *                         \c 100.
     * \param[in]  option      Option. Allowed values are:
     *                         \c DRAW to just draw a slider/scrollbar
     *                         (default),
     *                         \c REMOVE (currently unsupported),
     *                         \c DISABLED to draw a disabled slider/scrollbar,
     *                         \c REDRAW to redraw a slider/scrollbar.
     * \param[in]  page        Controls size of the moving rectangle for a
     *                         scrollbar widget only.
     */
    void slider( int id, int theme,
                 uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                 int orientation=HORIZONTAL, bool scrollbar=false,
                 int initial=0, int max=100, uint32_t option=DRAW, int page=1 );

    /**
     * Set value for an analog meter widget.
     * \param[in]  id    Widget ID.
     * \param[in]  value Numeric value to set.
     */
    void ameter_value( int id, int value );

    /**
     * Set value for a digital meter widget.
     * \param[in]  id    Widget ID.
     * \param[in]  value Numeric value to set.
     */
    void dmeter_value( int id, int value );

    /**
     * Set value for a progress widget.
     * \param[in]  id    Widget ID.
     * \param[in]  value Numeric value to set.
     */
    void progress_value( int id, int value );

    /**
     * Set value for a static widget.
     * \param[in]  id    Widget ID.
     * \param[in]  value String value to be set.
     */
    void static_value( int id, const char *value );

    /**
     * Wait for carriage-return teriminated data from ezLCD and store it in
     * the class's internal buffer. ezLCD is allowed 100 milliseconds to
     * produce carriage-return terminated data.
     * \return     Number of characters read.
     * \retval  0  Returns \c 0 when timeout occurs or response contains 
     *             carriage-return only.
     */
    inline int pollLCD();

    /**
     * Wait for carriage-return teriminated data from ezLCD and store it in
     * the class's internal buffer.
     * \param[in]  timeout    Time amount in milliseconds that will be allowed
     *                        for ezLCD to produce carriage-return terminated
     *                        data.
     * \return                Number of characters read.
     * \retval  0             Return \c 0 when timeout occurs or response
     *                        contains carriage-return only.
     */
    inline int pollLCD( unsigned long timeout );

    /* The following user-friendly functions are to be used after you manually
     * poll data from ezLCD */
      
    /**
      * After polling data from ezLCD, check the buffer for information on
      * wether the button with the specified widget ID was pressed. 
      * \param[in]  id     Widget ID of the button you want to check.
      * \retval     true   ezLCD signals that the button was pressed.
      * \retval     false  There is no information of the button with the
      *                    specified ID being pressed.
      */
    bool wasPressed( int id );

    /**
      * After polling data from ezLCD, check the buffer for information on
      * wether the button with the specified widget ID was released. 
      * \param[in]  id     Widget ID of the button you want to check.
      * \retval     true   ezLCD signaled that the button was released.
      * \retval     false  There is no information of the button with the
      *                    specified ID being released.
      */
    bool wasReleased( int id );

    /**
      * After polling data from ezLCD, check the buffer for information on
      * wether the checkbox with the specified widget ID was checked. 
      * \param[in]  id     Widget ID of the checkbox you want to check.
      * \retval     true   ezLCD signaled that the checkbox was checked.
      * \retval     false  There is no information of the checkbox with the
      *                    specified ID being checked.
      */
    bool wasChecked( int id );

    /**
      * After polling data from ezLCD, check the buffer for information on
      * wether the checkbox with the specified widget ID was unchecked. 
      * \param[in]  id     Widget ID of the checkbox you want to check.
      * \retval     true   ezLCD signaled that the checkbox was unchecked.
      * \retval     false  There is no information of the checkbox with the
      *                    specified ID being unchecked.
      */
    bool wasUnchecked( int id );

    /**
      * After polling data from ezLCD, check the buffer for information on
      * wether the radio button with the specified widget ID was selected. 
      * \param[in]  id     Widget ID of the radio button you want to check.
      * \retval     true   ezLCD signaled that the radio button was selected.
      * \retval     false  There is no information of the radio button with
      *                    the specified ID being selected.
      */
    bool wasSelected( int id );

    /**
     * After polling data from ezLCD, check the buffer for information about
     * a slider's changed position.
     * \param[in]  id    Widget ID of the slider you want to check.
     * \return           When ezLCD signals that the slider position has
     *                   changed, return the numeric value for the new 
     *                   position.
     * \retval     -1    There is no information of the slider with the
     *                   specified ID having it's position changed.
     */
    int getSlider( int id );


    /* Below are low-level commands for advanced users */
    
    /**
     * Send an EarthSEMPL command via a null-terminated string. (This is a low-
     * level function that is not required for most common uses of the device)
     * \param[in]  cmd    Null-terminated string containing the command that
     *                    will be sent to the ezLCD. This string does not need
     *                    to have a carriage-return at the end because
     *                    carriage-return gets automatically appended when
     *                    sending data to the ezLCD.
     */
    void sendCommand( const char *cmd );
    
    /**
     * Send an EarthSEMPL command from the class's internal buffer. The buffer
     * does not need to have a carriage-teturn at the end of the string because
     * it gets automatically appended when sending data to the ezLCD. (This is 
     * a low-level function that has easier-to-use alternatives for most common
     * uses of the device)
     */
    void sendCommand();

    /**
     * Wait for data from ezLCD terminated by a character. When available,
     * the data from ezLCD is stored in a buffer. (This is a low-level function
     * that is not required for most common uses of the device)
     * \param[in]  buf        Buffer where data from ezLCD is to be stored when
     *                        available.
     * \param[in]  bufsize    Buffer size.
     * \param[in]  timeout    Time amount in milliseconds that will be allowed
     *                        for ezLCD to produce a character-terminated
     *                        data. Default is \c 100 milliseconds.
     * \param[in]  terminator Terminating character. Default is \c '\r' 
     *                        (carriage-return character).
     * \return                Number of characters read.
     * \retval  0             Return \c 0 when timeout occurs or response
     *                        contains terminating character only.
     */
     int pollLCD( char *buf,
                  size_t bufsize,
                  unsigned long timeout = 100L,
                  char terminator = '\r' );

    /**
     * Return pointer to the class's internal character buffer. (This is a 
     * low-level command that is not required for most common uses of the
     * device)
     * \return  Pointer to the class's internal character buffer. This buffer
     *          is of size \c EZLCD_BUFSIZE.
     */
    char *buf() { return m_buf; }

    /**
     * Numerical values for the EarthSEMPL commands. Provided here for
     * users who wish to compose EarthSEMPL commands manually. (This is a low-
     * level asset that is not required for the common uses of the device)
     */    
     enum Commands {
         Command=             0,     /**< Direct command. */
         Status=              1,
         Clr_Screen=          2,     /**< Clear to provided color. */
         Ping=                3,     /**< Return Pong */
         zBeep=               4,     /**< Beep provided duration 
                                      *(frequency fixed) */
         Light=               5,     /**< \c 0 (off) to \c 100 (on) */
         Color=               6,
         eColor_ID=           7,

         Font=                10,    /**< Font number. */
         Fontw=               11,    /**< Font number widget. */
         Font_Orient=         12,    /**< Horizontal or vertical. */
         Line_Width=          13,    /**< 1 or 3. */
         Line_Type=           14,    /**< 1=dot dot 2=dash dash. */
         eXY=                 15,    /**< X and Y. */
         StringID=            16,    /**< SID ASCII String or File Name that
                                      * ends with 0. */
         Plot=                17,    /**< Place Pixel at X and Y. */
         eLine=               18,    /**< Draw a line to X and Y. */
         Box=                 19,    /**< Draws a Box to X and Y optional
                                      * fill. */
         zCircle=             20,    /**< Draws a Circle with Radius optional
                                      * fill */
         Arc=                 21,    /**< Draws an Arc with Radius and Begin 
                                      * Angle to End Angle. */
         Pie=                 22,    /**< Draws a Pie figure with Radius and
                                      * Begin Angle to End Angle and fills
                                      * it. */
         Picture=             24,    /**< Places a Picture on display. */
         Print=               25,    /**< Places the string on display which
                                      * ends with 0. */
         Beep_Freq=           26,    /**< Set the beeper frequency. */
         Calibrate=           28,    /**< Calibrate touch screen. */
         zReset=              29,    /**< Reset. */

         Rec_Macro=           30,    /**< Record Macro to flash drive. */
         Play_Macro=          31,    /**< Play Macro. */
         Stop_Macro=          32,    /**< Stop Macro. */
         Pause_Macro=         33,    /**< Pause n msec. */
         Loop_Macro=          34,    /**< Loop on Macro. */
         Speed_Macro=         35,    /**< Set the macro speed. */
         Peri=                36,
         ConfigIO=            37,
         IO=                  38,
         IOG=                 39,

         Security=            40,    /**< Set drive security string. */
         Location=            41,    /**< LID Location Vlaue. */
         Upgrade=             43,
         Parameters=          45,
         ClipEnable=          46,    /**< Set clip Enable. */
         ClipArea=            47,    /**< Set clip area. */

         /* Filesystem operations */
         Comment=             50,
         Fsgetcwd=            51,
         Fschdir=             52,
         Fsmkdir=             53,
         Fsrmdir=             54,
         Fsdir=               55,
         Fscopy=              56,
         Fsrename=            57,
         Fsremove=            58,
         Fsmore=              59,
         Format=              60,    /**< Format Flash Drive if string1 = 
                                      * "ezLCD" */
         If=                  61,
         Cmd=                 62,

         /* Widget commands */
         Set_Button=          70,    /**< Widget Button. */
         Set_CheckBox=        71,    /**< Widget Checkbox. */
         Set_Gbox=            72,    /**< Widget Group Box. */
         Set_RadioButton=     73,    /**< Widget Radio Button. */
         Set_DMeter=          74,    /**< Widget Digital Meter. */
         DMeter_Value=        75,    /**< Set DMeter value. */
         Set_AMeter=          76,    /**< Widget Analog Meter. */
         AMeter_Value=        77,    /**< Set AMeter value. */
         Set_Dial=            80,    /**< Widget RoundDial. */
         Set_Slider=          82,    /**< Widget Slider. */
         Set_Progress=        85,    /**< Widget Progress bar. */
         Progress_Value=      86,    /**< Progress value. */
         Set_StaticText=      87,    /**< Widget Static text. */
         StaticText_Value=    88,    /**< Static text Value. */
         Choice=              89,    /**< Widget get choice. */

         Widget_Theme=        90,    /**< Widget Scheme. */
         Widget_Values=       91,

         Mode=                98,
         Comport=             99,

         Xmax=                100,   /**< Return Xmax width. */
         Ymax=                101,   /**< Return Ymax height. */
         Wait=                102,   /**< Wait for touch. */
         Waitn=               103,   /**< Wait for no touch. */
         Waitt=               104,   /**< Wait for touch. */
         Threshold=           105,   /**< Touch threshold. */
         Verbose=             106,   /**< Controls the verbose mode. */
         Lecho=               107,   /**< Controls the echo mode. */
    };

/* Declares enums in the local class scope when \c EZLCD_GLOBALENUMS is 1 */
#if !EZLCD_GLOBALENUMS
    EZLCD_ENUM_ORIENTATION
    EZLCD_ENUM_ALIGNMENT
    EZLCD_ENUM_COMBALIGN
    EZLCD_ENUM_WIDGETS
    EZLCD_ENUM_CHOICE
#endif

protected:

    /**
     * Pointer to an instance of a serial communication class which is either
     * \c HardwareSerial (provided by Arduino) or \c SoftwareSerial (provided
     * in Arduino 1.0 and written by David A. Mellis).
     */
    Stream *m_pStream;
    
    /**
     * Establish communication with the ezLCD by sending "ping" commands and
     * waiting for a "Pong" or "0" response. \c m_echo and \c m_verbose are
     * set accordingly based on a response.
     */
    void findEzLCD();
    
    /**
     * Return wether the hardware or software serial class is being used.
     * \retval  true     \c HardwareSerial class is being used.
     * \retval  false    \c SoftwareSerial class is being used.
     */
    inline bool isHWSerial();

private:

    /**
     * Character buffer used to store EarthSempl commands before sending,
     * to store replies to commands from the ezLCD and to store data manually
     * polled from ezLCD by user.
     */
    char m_buf[ EZLCD_BUFSIZE ];

    /**
     * Maintain information on whether ezLCD currenly echoes its input. \c true
     * when it does and \c false otherwise.
     */
    bool m_echo;

    /**
     * Maintain information on whether ezLCD currently provides verbose output
     * to commands. True when it does and \c false otherwise.
     */
    bool m_verbose;

    /**
     * Read an integer from a c-string pointer, advance the pointer to after
     * the end of the read integer. 
     * \return    Integer value read from the string.
     */
    int readInt( char* &ptr );
    
    /**
     * Read a single integer from the class's internal character buffer.
     * \return    Integer value read from the class's internal character
     *            buffer.
     */
    int readInt();
    
    /**
     Return a justification string for the EarthSempl "print" command
     * \param[in]  align
     * \return     Justification string for the "print" command. Can be either
     *             \c "LT", \c "CT", \c "RT", \c "LC", \c "CC", \c "RC",
     *             \c "LB", \c "RB.
     */
    const char* jstStr( uint32_t align );

    /* Execute a command stored in \c m_buf and eat the echo and verbose
     * outputs if \c m_echo and \c m_verbose are set, respectively.
     * \return    Return value of the last call to \c pollLCD() used by
     *            this function, which is the number of bytes successfully 
     *            read by that last call.
     */
    int simpleCmd();
};

/**
 * Class derived from \c EzLCD3xx that uses the Arduino's hardware serial
 * class \c HardwareSerial. 
 */
class EzLCD3xx_HW : public EzLCD3xx
{
public:

    /**
     * Class constructor. Requires no parameters because hardware serial
     * implies \c pin \c 0 for receive and \c pin \c 1 for transmit.
     */
    EzLCD3xx_HW();
    
    void begin( long baud );
};

/** 
 * Class that derived from \c EzLCD3xx that uses Arduino's software serial
 * class \c SoftwareSerial.
 */

class EzLCD3xx_SW : public EzLCD3xx
{
public:

    /**
     * Class constructor
     * \param[in]  rx    Receive pin to be used.
     * \param[in]  tx    Transmit pin to be used.
     */
    EzLCD3xx_SW( int rx, int tx );
    void begin( long baud );

#if EZLCD_SERIALDEBUG
    /**
     * Debugging function to be called from the main loop of an Arduino code
     * in order to forward bytes from Arduino's hardware serial port to the
     * software serial port talking to ezLCD and read the response back.
     */
    void forwardSerial();
#endif

private:

    /**
     * Instance of a \c SoftwareSerial class that is controlling the ezLCD.
     */
    SoftwareSerial m_sws;
#if EZLCD_SERIALDEBUG
    /**
     * \c true when initialization for debugging over the hardware serial has
     * been completed.
     */
    static bool s_sdebugInit;
#endif
};

#endif // END #ifndef _EZLCD3XX_H
